package com.yomahub.liteflow.example.threadproject;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class Demo3 {
    private static final AtomicInteger counter = new AtomicInteger(0); // 用于线程安全的计数

    public static void executorBuilder() {
        ExecutorService executor = Executors.newFixedThreadPool(5);

        for (int j = 0; j < 5; j++) {
            executor.execute(new MyTask(counter));
        }

        executor.shutdown();

        if (executor.isTerminated()) {
            System.out.println("所有线程执行完毕，计数器值为：" + counter.get());
        }
    }

    public static void main(String[] args) {
//        for (int i = 0; i < 4; i++) {
////            executorBuilder();
//
//
//        }
        SingletonThreadPool executor = SingletonThreadPool.getInstance();
        for (int j = 0; j < 5; j++) {
            executor.execute(new MyTask(counter));
        }

        executor.shutdown();
        if (executor.isTerminated()) {
            System.out.println("所有线程执行完毕，计数器值为：" + counter.get());
        }
    }

}


class MyTask implements Runnable {
    private AtomicInteger atomicInteger;

    public MyTask(AtomicInteger atomicInteger) {
        this.atomicInteger = atomicInteger;
    }


    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            atomicInteger.incrementAndGet(); // 线程安全的计数
            System.out.println(System.currentTimeMillis() + " 线程id：" + Thread.currentThread().getId() + " 线程名：" + Thread.currentThread().getName() + " 执行任务：" + i);
        }
    }
}

//潜在问题和风险
//异常处理： 线程中运行的代码如果发生异常，会直接抛出到线程池的内部线程中，主线程可能无法捕获到这些异常。这可能会导致一些错误无法被及时发现和处理。建议在lambda表达式中添加try-catch块，适当处理可能发生的异常，或者至少记录异常日志。
//资源泄露： 使用ExecutorService时，调用shutdown()方法只是阻止了新任务的提交，并不会立即终止正在执行的任务。如果线程池中的任务执行时间很长，或者有阻塞操作，可能需要更强制的关闭方式，比如shutdownNow()，并且需要处理尚未完成的任务。
//线程安全： 在本例中，由于只是简单的打印操作，线程安全问题不明显。但如果lambda表达式中的逻辑更复杂，涉及到共享资源的读写，就需要考虑线程同步的问题，避免数据竞争和一致性问题。
//优化方向
//性能效率： 当前代码中，线程池的大小被硬编码为5，这可能不是对所有场景都是最优的选择。在实际应用中，应该根据任务的类型（CPU密集型还是IO密集型）以及系统的实际资源情况来动态调整线程池的大小，以达到最佳的性能表现。
//可维护性： 目前的任务只是简单的打印操作，实际应用中任务的逻辑会复杂得多。建议将任务的代码封装成单独的类或者方法，这样做不仅有利于代码的重用，也使得代码更易于阅读和维护。
//等待所有任务完成： 如果需要确保所有提交给线程池的任务都执行完成，可以在调用executor.shutdown()之后，使用awaitTermination方法等待线程池关闭。这样可以确保所有任务执行完成，或者在指定的时间内等待任务完成，这对于需要确保任务执行完毕的场景非常有用。
//日志记录： 目前的打印信息虽然能够提供一些基本的调试信息，但在实际的生产环境中，建议使用日志框架（如SLF4J、Log4j等）来记录日志。日志框架通常提供了灵活的日志级别控制和日志输出格式配置，更适用于生产环境中的日志记录和管理。